<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    
  </style>
</head>
<body>
  <div class="box">
    <p>我的名字叫：{{ name }},{{name  }},{{   name}}</p>
    <p>我的年龄是：{{age}}</p>
    <p>我的性别是：{{sex}}</p>
    <p>我的年龄是：{{age}}</p>
    <p>我的性别是：{{sex}}</p>
    <p>我的年龄是：{{age}}</p>
    <p>我的性别是：{{sex}}</p>
    <p>我的性别是：sex</p>
    <p>我的信息是：{{msg}}</p>
  </div>
</body>
<script>

  const vm = Vue({
    // 传入页面模板标志
    el:".box",
    // 传入要代理的目标对象
    data:{
      name:"admin",
      age:18,
      sex:"男",
      msg:"helloworld"
    }
  })

  // 自定义Vue的响应式数据
  function Vue( ops ){
    // 解析要代理的目标数据
    const obj = ops.data;
    // 获取页面模板中的数据标志
    const reg = /{{\s*[\w$]+\s*}}/g;
    // 从页面模板中的数据标志中获取数据名
    const reg2 = /[a-z_$][\w$]*/g;
    // 选择器页面模板元素
    const box = document.querySelector(ops.el)
    // 获取页面模板内容
    const str = box.innerHTML;
    // 页面模板初始渲染
    render(str);
    // 数据代理，数据劫持，添加访问器和控制器
    const result = new Proxy(obj, {
      get(target, attr){
        return target[attr];
      },
      set(target, attr, val){
        target[attr] = val;
        render(str);
      }
    })
    function render(str){
      // 从页面模板内容中获取所有数据标志
      const arr = str.match(reg);
      // 遍历所有数据标志
      arr.forEach(val=>{
        // 获取数据标志内的数据名
        const key = val.match(reg2)[0];
        // 使用字符串替换方法，根据数据标志替换成对应的真实数据
        str = str.replace(val, obj[key]);
      })
      // 将页面模板内容重新放回页面
      box.innerHTML = str;
    }
    // 返回代理之后的对象，方便外部二次操作
    return result;
  }





  
</script>
</html>